/* This file is part of the Crimsoon project
  * Copyright (C) 2009 Eduardo Henrique <eduardohleite@gmail.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public License
  * along with this library; see the file COPYING.LIB.  If not, write to
  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301, USA.
*/

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QVariant>
#include <QDir>
#include <QByteArray>
#include <QFileInfo>
#include <QStringList>

#include <fileref.h>
#include <mpegfile.h>
#include <id3v2tag.h>
#include <attachedpictureframe.h>

#include "gallery.h"
#include "querylibrary.h"
#include "musicfile.h"
#include "album.h"

#define GALLERY "GALLERY"

bool Gallery::connect()
{
    QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE", GALLERY);
    database.setDatabaseName("/home/eduardo/Projects/crimsoon/Crimsoon/data/gallery.db");

    return database.open();
}

void Gallery::disconnect()
{
    QSqlDatabase::database("GALLERY").close();
    QSqlDatabase::removeDatabase("GALLERY");
}

qint32 Gallery::getTotalFiles()
{
    qint32 result = 0;
    QSqlQuery query(QUERY_GALLERY_FILE_COUNT, QSqlDatabase::database(GALLERY));
    QString error;

    if (query.next())
    {
        result = query.value(0).toInt();
    }

    return result;
}

bool Gallery::removeAudioFile(QString path)
{
    QSqlQuery query(QSqlDatabase::database(GALLERY));
    query.prepare(QUERY_GALLERY_AUDIO_REMOVE);
    query.bindValue(":path", path);

    return query.exec();
}

bool Gallery::addAudioFile(MusicFile fileInfo, qint32 dirCode)
{
    QSqlQuery query(QSqlDatabase::database(GALLERY));
    QString album;
    QString artist;
    QString title;
    QFileInfo resolver(fileInfo.fileName);

    album = (fileInfo.album.isEmpty() ? "Unknown Album" : fileInfo.album);
    artist = (fileInfo.album.isEmpty() ? "Unknown Artist" : fileInfo.artist);
    title = (fileInfo.title.isEmpty() ? resolver.baseName() : fileInfo.title);

    query.prepare(QUERY_GALLERY_AUDIO_ADD);
    query.bindValue(":path",     fileInfo.fileName);
    query.bindValue(":title",    fileInfo.title);
    query.bindValue(":album",    album);
    query.bindValue(":track",    fileInfo.track);
    query.bindValue(":artist",   artist);
    query.bindValue(":year",     fileInfo.year);
    query.bindValue(":length",   fileInfo.length);
    query.bindValue(":bitrate",  fileInfo.bitRate);
    query.bindValue(":dir",      dirCode);

    return query.exec();
}

void Gallery::beginBulk()
{
    QSqlDatabase::database(GALLERY).transaction();
}

void Gallery::endBulk()
{
    QSqlDatabase::database(GALLERY).commit();
}

QStringList Gallery::getAllArtistNames()
{
    QStringList artists;

    QSqlQuery query(QUERY_GALLERY_AUDIO_ALL_ARTISTS, QSqlDatabase::database(GALLERY));
    while (query.next())
    {
        artists << query.value(0).toString();
    }

    return artists;
}

QStringList Gallery::getAllAlbunsByArtist(QString artist)
{
    QList<QString> albums;

    QSqlQuery query(QSqlDatabase::database(GALLERY));
    query.prepare(QUERY_GALLERY_AUDIO_ALL_ALBUMS);
    query.bindValue(":artist", artist);

    if (query.exec())
    {
        while (query.next())
        {
            albums << query.value(0).toString();
        }
    }

    return albums;
}

qint32 Gallery::addScanDir(QString path)
{
    QSqlQuery insert(QSqlDatabase::database(GALLERY));
    qint32 result = 0;

    insert.prepare(QUERY_GALLERY_DIR_ADD);
    insert.bindValue(":path", path);

    if (insert.exec())
    {
        QSqlQuery select(QUERY_GALLERY_DIR_LAST, QSqlDatabase::database(GALLERY));
        if (select.next())
        {
            result = select.value(0).toInt();
        }
    }

    return result;
}

bool Gallery::hasPath(QString path)
{
    bool result = false;
    QSqlQuery query(QSqlDatabase::database(GALLERY));
    query.prepare(QUERY_GALLERY_DIR_EXISTS);
    query.bindValue(":path", path);

    if (query.exec())
    {
        if (query.next())
        {
            result = true;
        }
    }

    return result;
}

AlbumStatus Gallery::hasAlbum(Album album)
{
    AlbumStatus result = AlbumNotExists;
    QSqlQuery query(QSqlDatabase::database(GALLERY));

    query.prepare(QUERY_GALLERY_ALBUM_EXISTS_HAS_PICTURE);
    query.bindValue(":artist", album.artist);
    query.bindValue(":album", album.title);

    if (query.exec())
    {
        if (query.next())
        {
            result = (query.value(0).toInt() == 0 ? AlbumNoPicture : AlbumHasPicture);
        }
    }

    return result;
}

bool Gallery::addAlbum(Album album)
{
    QSqlQuery query(QSqlDatabase::database(GALLERY));

    if (album.picture != NULL && (!album.picture->isEmpty()) && album.picture->at(0)!= '\0')
    {
        query.prepare(QUERY_GALLERY_ALBUM_ADD_PICTURE);
        query.bindValue(":picture", *album.picture);
    }
    else
    {
        query.prepare(QUERY_GALLERY_ALBUM_ADD);
    }

    query.bindValue(":artist", album.artist);
    query.bindValue(":album", album.title);

    return query.exec();
}

bool Gallery::removeFilesFromDir(QString path)
{
    QSqlQuery query(QSqlDatabase::database(GALLERY));
    query.prepare(QUERY_GALLERY_DIR_REMOVE);
    query.bindValue(":dir", path);
    return query.exec();
}

Album Gallery::getAlbum(QString artist, QString title)
{
    Album result;
    QSqlQuery query(QSqlDatabase::database(GALLERY));

    query.prepare(QUERY_GALLERY_ALBUM_SELECT);
    query.bindValue(":artist", artist);
    query.bindValue(":album", title);

    if (query.exec())
    {
        if (query.next())
        {
            result.code = query.value(0).toInt();
            result.title = query.value(1).toString();
            result.artist = query.value(2).toString();
            result.picture = new QByteArray(query.value(3).toByteArray());
        }
    }

    return result;
}

QSqlQuery Gallery::getQueryAllFiles()
{
    QSqlQuery query(QUERY_GALLERY_FILE_ALL, QSqlDatabase::database(GALLERY));
    return query;
}

QSqlQuery Gallery::getQueryArtistFiles(QString artist)
{
    QSqlQuery query(QSqlDatabase::database(GALLERY));
    query.prepare(QUERY_GALLERY_FILE_ARTIST);
    query.bindValue(":artist", artist);
    query.exec();

    return query;
}

QSqlQuery Gallery::getQueryAlbumFiles(QString artist, QString album)
{
    QSqlQuery query(QSqlDatabase::database(GALLERY));
    query.prepare(QUERY_GALLERY_FILE_ALBUM);
    query.bindValue(":artist", artist);
    query.bindValue(":album", album);
    query.exec();

    return query;
}

MusicFile Gallery::getMusicFileInfo(QString path)
{
    MusicFile musicFile;
    QFileInfo resolver(path);

    TagLib::FileRef mediaInfo(qPrintable(path));

    musicFile.fileName = path;
    musicFile.title    = QString::fromStdString(mediaInfo.tag()->title().to8Bit(true));
    musicFile.artist   = QString::fromStdString(mediaInfo.tag()->artist().to8Bit(true));
    musicFile.album    = QString::fromStdString(mediaInfo.tag()->album().to8Bit(true));
    musicFile.genre    = QString::fromStdString(mediaInfo.tag()->genre().to8Bit(true));
    musicFile.track    = mediaInfo.tag()->track();
    musicFile.year     = mediaInfo.tag()->year();
    musicFile.length   = mediaInfo.audioProperties()->length();
    musicFile.bitRate  = mediaInfo.audioProperties()->bitrate();

    if (resolver.completeSuffix() == "mp3")
    {
        TagLib::MPEG::File mpegFile(path.toLatin1());
        if (mpegFile.ID3v2Tag())
        {
            TagLib::ID3v2::FrameList mpegFrames = mpegFile.ID3v2Tag()->frameListMap()["APIC"];
            if (!mpegFrames.isEmpty())
            {
                TagLib::ID3v2::AttachedPictureFrame *mpegPictureFrame = static_cast<TagLib::ID3v2::AttachedPictureFrame *> (mpegFrames.front());
                musicFile.picture = new QByteArray(mpegPictureFrame->picture().data(), mpegPictureFrame->picture().size());
                //delete mpegPictureFrame;
            }
        }
    }

    return musicFile;
}

Gallery::Gallery()
{
    connect();
}

Gallery::~Gallery()
{
    disconnect();
}
